package bancosys.tec.rtm.diagnostician;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;

import bancosys.tec.rtm.diagnostician.report.DiagnosticianReportGenerator;

/**
 * Diagnostician case que busca os diagnosticadores da BeanFactory. Deve ser cadastrada na beanFactory para funcionar.
 * 
 * @author takeshi
 */
public class BeanFactoryDiagnosticianCase implements DiagnosticianCase, BeanFactoryAware, InitializingBean {

    private volatile ListableBeanFactory listableBeanFactory;

    private volatile List<Diagnostician> diagnosticians = new ArrayList<Diagnostician>();

    /**
     * {@inheritDoc}
     */
    public void executeDiagnostician(DiagnosticianReportGenerator reportGenerator, OutputStream outputStream) throws Exception {
        this.executeDiagnosticianInDebugMode(reportGenerator, outputStream);
    }

    /**
     * {@inheritDoc}
     */
    public void executeDiagnosticianInDebugMode(DiagnosticianReportGenerator reportGenerator, OutputStream outputStream) throws Exception {
        DiagnosticianController controller = new DiagnosticianController(reportGenerator);
        controller.addDiagnosticianList(getDiagnosticiansListOfSystemInDebugMode());
        controller.generateReportOfDiagnosticians(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    /**
     * {@inheritDoc}
     */
    public List<Diagnostician> getDiagnosticiansListOfSystem() {
        return this.getDiagnosticiansListOfSystemInDebugMode();
    }

    /**
     * {@inheritDoc}
     */
    public List<Diagnostician> getDiagnosticiansListOfSystemInDebugMode() {
        this.diagnosticians.clear();
        final ListableBeanFactory bf = this.listableBeanFactory;
        if (bf != null) {
            String[] diagnosticianBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, Diagnostician.class);
            for (String string : diagnosticianBeanNames) {
                Diagnostician diag = (Diagnostician) bf.getBean(string);
                this.diagnosticians.add(diag);
            }
        }
        return diagnosticians;
    }

    /**
     * {@inheritDoc}
     */
    public void setBeanFactory(BeanFactory beanFactory) {
        if (beanFactory instanceof ListableBeanFactory) {
            this.listableBeanFactory = (ListableBeanFactory) beanFactory;
        }
    }

    /**
     * {@inheritDoc}
     */
    public void afterPropertiesSet() throws Exception {
        final ListableBeanFactory bf = this.listableBeanFactory;
        if (bf != null) {
            String[] diagnosticianBeanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, Diagnostician.class);
            for (String string : diagnosticianBeanNames) {
                Diagnostician diag = (Diagnostician) bf.getBean(string);
                this.diagnosticians.add(diag);
            }
        }
    }

}
